package org.dreamland.infrastructure.security

import jakarta.servlet.http.HttpSession
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken
import org.springframework.security.authentication.dao.DaoAuthenticationProvider
import org.springframework.security.core.userdetails.UserDetails
import org.springframework.security.core.userdetails.UserDetailsService
import org.springframework.security.crypto.password.PasswordEncoder
import org.springframework.web.context.request.RequestAttributes
import org.springframework.web.context.request.RequestContextHolder
import org.springframework.web.context.request.ServletRequestAttributes
import java.util.*

/**
 * 账户密码人机验证认证提供者
 *
 * @author DYM
 * @date 2024/5/8 17:13
 */
class UsernamePasswordCaptchaAuthenticationProvider(
        private val graphicCaptchaManager: GraphicCaptchaManager,
        userDetailsService: UserDetailsService,
        passwordEncoder: PasswordEncoder
) : DaoAuthenticationProvider(passwordEncoder) {

    init {
        super.setUserDetailsService(userDetailsService)
    }

    override fun supports(authentication: Class<*>): Boolean {
        return (UsernamePasswordCaptchaAuthenticationToken::class.java.isAssignableFrom(authentication))
    }

    //    @Throws(AuthenticationException::class)
    override fun additionalAuthenticationChecks(userDetails: UserDetails, authentication: UsernamePasswordAuthenticationToken) {
        super.additionalAuthenticationChecks(userDetails, authentication)

        val targetAuthentication: UsernamePasswordCaptchaAuthenticationToken = authentication as UsernamePasswordCaptchaAuthenticationToken
        val captcha: String = targetAuthentication.captcha

        val session: HttpSession = (Objects.requireNonNull<RequestAttributes>(RequestContextHolder.getRequestAttributes()) as ServletRequestAttributes).getRequest().getSession()

        if (graphicCaptchaManager.matches(session.id, captcha)) {
            return
        }
        throw BadCaptchaException("验证码错误")
    }
}
